

using System;
using System.Threading;
using Microsoft.NETMF.BikeComputer.Hardware;


//--//

namespace Microsoft.NETMF.BikeComputer.Application
{

   //--//

    public class RideDataModel
    {
        public delegate void InclineChangedEventHandler(double incline);
        public delegate void RideDataChangedEventHandler(double incline,double speed, double distance, double cadence, double temperature);

        //--//

        public RideDataModel()
        {
            _distance = 0;
            _today = DateTime.Now;  //change this later.
        }


        #region constants

        //This is only an approximation of an accurate circumference for now.  
        //This is complicated by where the tire is seated relative to the rim and the size of the tire.
        //There are also other tire size designations which could be used instead or as well as these
        
        private static TireSize[] TireSizeTable = new TireSize[] { 
                                                    new TireSize ("26x1-1/4", 1911),
                                                    new TireSize ("26x1-3/8", 1889),
                                                    new TireSize("26x1-1/2", 1889),
                                                    new TireSize("26x1-3/4", 1880),
                                                    //new TireSize("26x1-3/4",1873),
                                                    new TireSize ("27x1", 2128),
                                                    new TireSize ("27x1-1/4", 2134),
                                                    new TireSize ("27x1-3/8", 2128),
                                                    new TireSize ("27x1-1/2", 1993),
                                                    new TireSize ("28x1-1/4", 2183),
                                                    new TireSize ("28x1-3/8", 2166),
                                                    new TireSize ("28x1-1/2", 2144),
                                                    new TireSize ("28x1-5/8", 2144),
                                                    new TireSize ("28x1-3/4", 2166),
                                                                }; 


        public SettingsTable TireSizes = new SettingsTable(TireSizeTable);


        private static Units[] UnitsTable = new Units[]  { new Units(Resources.GetString(Resources.StringResources.MetricUnits)), new Units(Resources.GetString(Resources.StringResources.EnglishUnits)) };

 
        public SettingsTable Units = new SettingsTable(UnitsTable);


        private enum states { NotStarted, Riding, Paused, Done };


        #endregion



        #region events

 

        public DateTime getToday()
        {
            return _today;
        }

        #endregion

        //--//

        #region delegates

        
        #endregion

        //--//

        #region state query and notifications

        public double CurrentSpeed
        {
            get
            {
                return _speed;
            }
        }
   
        
        #endregion state query and notifications

        //--//

        #region state change

        public void processData(double incline, double temperature, ulong speed, ulong cadence, string eTime )   // convert counters and data input to valid data content for comsumption.  return true is data has changed
        {

            double _thisDistance;

            _thisDistance = (double)speed  *  ((TireSize)TireSizes.Current()).Circumference;

            if (Units.Current().Label == Resources.GetString(Resources.StringResources.MetricUnits))
            {
                _speed = _thisDistance * .00036;
                _distance += _thisDistance / 100000;
            }
            else
            {
                _speed = (double) speed * (ulong) ( ((TireSize)TireSizes.Current()).Circumference * .0022369);
                _distance += _thisDistance/100000 * .62;
            }

            _cadence = (double) cadence * 6;

            _temperature = temperature;

            if (Units.Current().Label == Resources.GetString(Resources.StringResources.EnglishUnits))
            {
                _temperature = _temperature * 9 / 5 + 32;
            }
            _incline = incline;

            OnRideDataChanged(_incline, _speed, _distance, _cadence, _temperature);
 
        }


        public double getSpeed()
        {
            return _speed;
        }


        public double getCadence()
        {
            return _cadence;
        }

        public double getDistance()
        {
            return _distance;
        }

        public double Incline
        {
            get
            {
                return _incline;      //inclineSensor.GetIncline();
            }
            set
            {
                double low = c_LowTolerance * _incline;
                double hig = c_HighTolerance * _incline;
                if ((value < low)  || hig < value)
                {
                    _incline = value;

                    if (OnInclineChanged != null)
                    {
                        OnInclineChanged(_incline);
                    }
                }
            }
        }

        public event InclineChangedEventHandler OnInclineChanged;
        public event RideDataChangedEventHandler OnRideDataChanged;


        public double Temperature
        {
            get
            {
                
                return _temperature;    
            }
            set
            {
                _temperature = value;
            }
        }

    

        #endregion state change

        //--//

        #region private members
        //--//
        const double c_LowTolerance = 0.98;
        const double c_HighTolerance = 1.02;
        //--//
        private double _speed;
        private double _cadence;
        private double _distance;
        private double _incline;
        private double _temperature;
        private DateTime _today;



        //settings
        
        //save unit preferences to SD card?  Weak references?
        //save tire size to SD card? Weak References?  Save tire circumfrence instead of diameter.
        
      
        #endregion private members

        #region public members
 
        #endregion public members
    }
}
